package com.ehsunbehravesh.mypasswords.gui;

import com.ehsunbehravesh.mypasswords.Domain;
import com.ehsunbehravesh.mypasswords.Logger;
import com.ehsunbehravesh.mypasswords.Utils;
import com.ehsunbehravesh.mypasswords.entity.PasswordEntry;
import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class ChangePasswordDialog2 extends javax.swing.JDialog {
  private JFileChooser openDialog;

  public ChangePasswordDialog2(JFrame parent, boolean modal) {
    super(parent, modal);
    initComponents();
    myInitComponents();
    Utils.setCenterOfParent((JFrame) getParent(), this);
  }

  @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pnlMain = new javax.swing.JPanel();
        txtOldPassword = new javax.swing.JPasswordField();
        lblOldPassword = new javax.swing.JLabel();
        txtPassword = new javax.swing.JPasswordField();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        txtConfirmation = new javax.swing.JPasswordField();
        btnOk = new javax.swing.JButton();
        btnCancel = new javax.swing.JButton();
        btnRecover = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Change Password");
        setResizable(false);

        pnlMain.setBackground(java.awt.Color.white);

        txtOldPassword.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                txtOldPasswordActionPerformed(evt);
            }
        });
        txtOldPassword.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtOldPasswordKeyPressed(evt);
            }
        });

        lblOldPassword.setText("Old password:");

        txtPassword.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtPasswordKeyPressed(evt);
            }
        });

        jLabel2.setText("New password:");

        jLabel3.setText("Confirmation:");

        txtConfirmation.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtConfirmationKeyPressed(evt);
            }
        });

        btnOk.setText("OK");
        btnOk.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnOkActionPerformed(evt);
            }
        });
        btnOk.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                btnOkKeyPressed(evt);
            }
        });

        btnCancel.setText("Cancel");
        btnCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCancelActionPerformed(evt);
            }
        });
        btnCancel.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                btnCancelKeyPressed(evt);
            }
        });

        btnRecover.setText("Old Password by Recovery File");
        btnRecover.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnRecoverActionPerformed(evt);
            }
        });
        btnRecover.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                btnRecoverKeyPressed(evt);
            }
        });

        javax.swing.GroupLayout pnlMainLayout = new javax.swing.GroupLayout(pnlMain);
        pnlMain.setLayout(pnlMainLayout);
        pnlMainLayout.setHorizontalGroup(
            pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlMainLayout.createSequentialGroup()
                .addGap(33, 33, 33)
                .addGroup(pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(pnlMainLayout.createSequentialGroup()
                        .addComponent(btnRecover, javax.swing.GroupLayout.DEFAULT_SIZE, 224, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnOk, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(pnlMainLayout.createSequentialGroup()
                        .addGroup(pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel2)
                            .addComponent(jLabel3)
                            .addComponent(lblOldPassword))
                        .addGap(38, 38, 38)
                        .addGroup(pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(txtConfirmation, javax.swing.GroupLayout.DEFAULT_SIZE, 265, Short.MAX_VALUE)
                            .addComponent(txtPassword, javax.swing.GroupLayout.DEFAULT_SIZE, 265, Short.MAX_VALUE)
                            .addComponent(txtOldPassword, javax.swing.GroupLayout.DEFAULT_SIZE, 265, Short.MAX_VALUE))))
                .addGap(39, 39, 39))
        );
        pnlMainLayout.setVerticalGroup(
            pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlMainLayout.createSequentialGroup()
                .addGap(33, 33, 33)
                .addGroup(pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(txtOldPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lblOldPassword))
                .addGap(18, 18, 18)
                .addGroup(pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel2)
                    .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel3)
                    .addComponent(txtConfirmation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnCancel)
                    .addComponent(btnOk)
                    .addComponent(btnRecover))
                .addContainerGap(28, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(pnlMain, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(pnlMain, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

  private void txtOldPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtOldPasswordActionPerformed
    // TODO add your handling code here:
  }//GEN-LAST:event_txtOldPasswordActionPerformed

  private void txtOldPasswordKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtOldPasswordKeyPressed
    int key = evt.getKeyCode();
    if (key == 10) {
      btnOkActionPerformed(null);
    } else if (key == 27) {
      btnCancelActionPerformed(null);
    }
  }//GEN-LAST:event_txtOldPasswordKeyPressed

  private void txtPasswordKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtPasswordKeyPressed
    int key = evt.getKeyCode();
    if (key == 10) {
      btnOkActionPerformed(null);
    } else if (key == 27) {
      btnCancelActionPerformed(null);
    }
  }//GEN-LAST:event_txtPasswordKeyPressed

  private void txtConfirmationKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtConfirmationKeyPressed
    int key = evt.getKeyCode();
    if (key == 10) {
      btnOkActionPerformed(null);
    } else if (key == 27) {
      btnCancelActionPerformed(null);
    }
  }//GEN-LAST:event_txtConfirmationKeyPressed

  private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed
    try {
      Domain domain = Domain.getInstance();
      String oldPassword = domain.getSetting("password", null);
      oldPassword = oldPassword != null ? oldPassword : "";
      String enteredOldPassword = new String(txtOldPassword.getPassword());
      enteredOldPassword = Utils.SHA256(enteredOldPassword);
      if (oldPassword.length() > 0 && !oldPassword.equals(enteredOldPassword)) {
        JOptionPane.showMessageDialog(this, "Incorrect password!", "Warning", JOptionPane.WARNING_MESSAGE);
      } else {
        if (txtPassword.getPassword().length >= 8) {
          if (!Arrays.equals(txtPassword.getPassword(), txtConfirmation.getPassword())) {
            JOptionPane.showMessageDialog(this, "Confirmation password doesn't match!", "Warning", JOptionPane.WARNING_MESSAGE);
          } else {
            if (domain.setHashedSetting("password", new String(txtPassword.getPassword()))) {

              // <editor-fold defaultstate="collapsed" desc="change all passes in database">
              PasswordEntry[] allPasswords = PasswordEntry.getAllPasswordEntries();
              domain.setPassword(new String(txtPassword.getPassword()));
              for (int i = 0; i < allPasswords.length; i++) {
                PasswordEntry passwordEntry = allPasswords[i];
                passwordEntry.save();
              }
              // </editor-fold>

              JOptionPane.showMessageDialog(this, "Your password changed successfully.", "Info", JOptionPane.INFORMATION_MESSAGE);
              setVisible(false);
              dispose();
              System.gc();
            } else {
              JOptionPane.showMessageDialog(this, "Error occured!", "Error", JOptionPane.ERROR_MESSAGE);
            }
          }
        } else {
          JOptionPane.showMessageDialog(this, "Your password should be at least 8 characters long!", "Warning", JOptionPane.WARNING_MESSAGE);
        }
      }
    } catch (NoSuchAlgorithmException ex) {
      Logger.log("Failed to hash password: " + ex.getMessage());
    } catch (Exception ex) {
      Logger.log("Exception: " + ex.getMessage());
    }
  }//GEN-LAST:event_btnOkActionPerformed

  private void btnOkKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_btnOkKeyPressed
    int key = evt.getKeyCode();
    if (key == 10) {
      btnOkActionPerformed(null);
    } else if (key == 27) {
      btnCancelActionPerformed(null);
    }
  }//GEN-LAST:event_btnOkKeyPressed

  private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
    setVisible(false);
    dispose();
    System.gc();
  }//GEN-LAST:event_btnCancelActionPerformed

  private void btnCancelKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_btnCancelKeyPressed
    int key = evt.getKeyCode();
    if (key == 10) {
      btnOkActionPerformed(null);
    } else if (key == 27) {
      btnCancelActionPerformed(null);
    }
  }//GEN-LAST:event_btnCancelKeyPressed

  private void btnRecoverActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRecoverActionPerformed
    btnRecoverActionPerform(evt);
  }//GEN-LAST:event_btnRecoverActionPerformed

  private void btnRecoverKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_btnRecoverKeyPressed
    int key = evt.getKeyCode();
    if (key == 10) {
      btnOkActionPerformed(null);
    } else if (key == 27) {
      btnCancelActionPerformed(null);
    }
  }//GEN-LAST:event_btnRecoverKeyPressed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnCancel;
    private javax.swing.JButton btnOk;
    private javax.swing.JButton btnRecover;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel lblOldPassword;
    private javax.swing.JPanel pnlMain;
    private javax.swing.JPasswordField txtConfirmation;
    private javax.swing.JPasswordField txtOldPassword;
    private javax.swing.JPasswordField txtPassword;
    // End of variables declaration//GEN-END:variables

  private void myInitComponents() {
    Domain domain = Domain.getInstance();
    String currentPassword = domain.getSetting("password", null);
    if (currentPassword == null || currentPassword.length() <= 0) {
      lblOldPassword.setVisible(false);
      txtOldPassword.setVisible(false);
    }

    txtOldPassword.requestFocus();
  }

  private void btnRecoverActionPerform(ActionEvent evt) {
    if (openDialog == null) {
      openDialog = new JFileChooser();
    }
    int answer = openDialog.showOpenDialog(this);
    
    if (answer != JFileChooser.CANCEL_OPTION) {
      File recoveryFile = openDialog.getSelectedFile();
      BufferedReader reader = null;
      try {
        reader = new BufferedReader(new FileReader(recoveryFile));
        String token = reader.readLine();
        String password = Utils.recoverPassword(token);
        
        txtOldPassword.setText(password);
      } catch (Exception ex) {
        Logger.log(ex.getMessage());
        JOptionPane.showMessageDialog(this, "Password recovery failed!", "Error", JOptionPane.ERROR_MESSAGE);
      } finally {
        if (reader != null) {
          try {
            reader.close();
          } catch (IOException ex) {
            Logger.log(ex.getMessage());
          }
        }
      }
    }
  }
}
